package com.zcj.demo.config;

import com.zcj.demo.user.domain.UserDO;
import com.zcj.demo.user.service.AccountService;
import com.zcj.demo.utils.TokenUtil;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;

/**
 * @author 68300119
 * @Date 2020/10/13
 **/
public class JwtAuthenticationProcessingFilter extends UsernamePasswordAuthenticationFilter {

    @Autowired
    private AccountService accountService;


    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        // 将 ServletRequest 转换为 HttpServletRequest 才能拿到请求头中的 token
        HttpServletRequest httpRequest = (HttpServletRequest) req;
        HttpServletResponse httpResponse = (HttpServletResponse) res;
        String uri = httpRequest.getRequestURI();
        // 如果请求为登录 或者 获取验证码 或者注册 就继续执行
        if ("/api/login/captcha".equals(uri)
                || "/api/login/account".equals(uri)
                || "/api/register".equals(uri)) {
            chain.doFilter(req, res);
            return;
        }
        // 尝试获取请求参数的 token
        String token = httpRequest.getHeader("Authorization");
        if (StringUtils.isNotEmpty(token)) {
            token = token.replaceAll("Bearer ", "");
            if (!TokenUtil.validateToken(token)) {
                httpResponse.setStatus(401);
                return;
            }
            if (SecurityContextHolder.getContext().getAuthentication() == null) {
                UserDO account = accountService.getSysAccountByToken(token);
                if (ObjectUtils.isEmpty(account)) {
                    httpResponse.setStatus(401);
                    return;
                }
                Set<GrantedAuthority> authorities = new HashSet<>();
                String[] roles = {"admin"};
                for (String role : roles) {
                    authorities.add(new SimpleGrantedAuthority(role));
                }
                UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(account, null, authorities);
                authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(httpRequest));
                // 将权限写入本次会话
                SecurityContextHolder.getContext().setAuthentication(authentication);
            }
        }

        chain.doFilter(req, res);
    }
}